﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;
using System.Xml;

namespace com.kmer.db.Helper
{
    public static class DbContextHelper {
		public static DbRawSqlQuery<T> SqlQuery<T>(this DbContext dc, string sql, params object[] parameters) {
			return SqlQuery<T>(dc.Database, sql, parameters);
		}
		public static DbRawSqlQuery<T> SqlQuery<T>(Database db, string sql, params object[] parameters) {
			return db.SqlQuery<T>(sql, parameters);
		}

		public static SqlParameter CreateParameter(this DbContext dc, string name, object value, ParameterDirection pDirection = ParameterDirection.Input) {
			var par = new SqlParameter {
				ParameterName = name,
				Value = value,
				Direction = pDirection
			};
			par.ResetDbType();
			return par;
		}
		public static SqlParameter CreateParameter<T>(this DbContext dc, string pName, T pValue, int pSize = 0) {
			var parame = new SqlParameter();
			if (pSize > 0) {
				parame.Size = pSize;
			}
			parame.Value = pValue;
			parame.ParameterName = pName;
			parame.ResetSqlDbType();
			return parame;
		}
		/// <summary>
		/// 与接受 SQL 的任何 API 一样，对任何用户输入进行参数化以便避免 SQL 注入攻击是十分重要的。 您可以在 SQL 查询字符串中包含参数占位符，然后将参数值作为附加参数提供。 您提供的任何参数值都将自动转换为 DbParameter。 context.Database.ExecuteSqlCommand("UPDATE dbo.Posts SET Rating = 5 WHERE Author = @p0", userSuppliedAuthor); 或者，您还可以构造一个 DbParameter 并将它提供给 SqlQuery。 这允许您在 SQL 查询字符串中使用命名参数。 context.Database.ExecuteSqlCommand("UPDATE dbo.Posts SET Rating = 5 WHERE Author = @author", new SqlParameter("@author", userSuppliedAuthor));
		/// </summary>
		/// <param name="dc"></param>
		/// <param name="sql"></param>
		/// <param name="parameters"></param>
		/// <returns></returns>
		public static int Execute(this DbContext dc, string sql, params object[] parameters) {
			return Execute(dc.Database, sql, parameters);
		}
		/// <summary>
		/// 与接受 SQL 的任何 API 一样，对任何用户输入进行参数化以便避免 SQL 注入攻击是十分重要的。 您可以在 SQL 查询字符串中包含参数占位符，然后将参数值作为附加参数提供。 您提供的任何参数值都将自动转换为 DbParameter。 context.Database.ExecuteSqlCommand("UPDATE dbo.Posts SET Rating = 5 WHERE Author = @p0", userSuppliedAuthor); 或者，您还可以构造一个 DbParameter 并将它提供给 SqlQuery。 这允许您在 SQL 查询字符串中使用命名参数。 context.Database.ExecuteSqlCommand("UPDATE dbo.Posts SET Rating = 5 WHERE Author = @author", new SqlParameter("@author", userSuppliedAuthor));
		/// </summary>
		/// <param name="db"></param>
		/// <param name="sql"></param>
		/// <param name="parameters"></param>
		/// <returns></returns>
		public static int Execute(Database db, string sql, params object[] parameters) {
			return db.ExecuteSqlCommand(sql, parameters);
		}
		public static T ExecutePropScalar<T>(this DbContext dc, string sql, params object[] parameters) {
			return ExecutePropScalar<T>(dc.Database, sql, parameters);
		}
		public static T ExecutePropScalar<T>(Database db, string sql, params object[] parameters) {
			return db.SqlQuery<T>(sql, parameters).FirstOrDefault();
		}
	
		/// <summary>
		/// 执行存储过程并返回数据集（过度）
		/// </summary>
		/// <param name="dc"></param>
		/// <param name="strSpName"></param>
		/// <param name="pParameters"></param>
		/// <returns></returns>
		public static DataSet DisplayData(this DbContext dc, string strSpName, params SqlParameter[] pParameters) {
			using (var conn = new SqlConnection(dc.Database.Connection.ConnectionString)) {
				conn.Open();
				var command = new SqlCommand(strSpName, conn);
				foreach (var k in pParameters) {
					command.Parameters.Add(k);
				}
				var adapter = new SqlDataAdapter(command);
				var dst = new DataSet();
				adapter.Fill(dst);
				return dst;
			}
		}
		public static IList<T> DisplayData<T>(this DbContext dc, string sql) where T : new() {
			return SqlQuery<T>(dc.Database, sql).ToList();
		}
		/// <summary>
		/// 执行存储过程并返回第一个数据表（过度）
		/// </summary>
		/// <param name="dc"></param>
		/// <param name="strNo"></param>
		/// <param name="strSearch"></param>
		/// <param name="strSpName"></param>
		/// <returns></returns>
		public static DataView DisplayDataView(this DbContext dc, string strNo, string strSearch, string strSpName) {
			using (var conn = new SqlConnection(dc.Database.Connection.ConnectionString)) {
				conn.Open();
				var command = new SqlCommand(strSpName, conn);
				command.Parameters.Add(dc.CreateParameter("@chrNo", strNo));
				command.Parameters.Add(dc.CreateParameter("@chrSearch", strSearch));
				var adapter = new SqlDataAdapter(command);
				var dst = new DataSet();
				adapter.Fill(dst);
				return dst.Tables[0].DefaultView;
			}
		}
		public static DataView DisplayDataView(this DbContext dc, string strNo, string strSpName) {
			using (var conn = new SqlConnection(dc.Database.Connection.ConnectionString)) {
				conn.Open();
				var command = new SqlCommand(strSpName, conn);
				command.Parameters.Add(dc.CreateParameter("@chrNo", strNo));
				var adapter = new SqlDataAdapter(command);
				var dst = new DataSet();
				adapter.Fill(dst);
				return dst.Tables[0].DefaultView;
			}
		}
	}// end class
}
